package ajaxjs.test;

import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import org.sqlite.SQLiteDataSource;
import org.sqlite.SQLiteJDBCLoader;

import ajaxjs.config.Application;
import ajaxjs.service.BaseServlet;

import com.mysql.jdbc.jdbc2.optional.MysqlDataSource;

public class MockRequest {
	
	public Class<?> getBusinessServletClass(){
		return null;
	}
	
	/**
	 * 初始化 Servlet 配置，这里是模拟 注解
	 * @return
	 */
	protected ServletConfig initServletConfig(){
		ServletConfig servletConfig = mock(ServletConfig.class);
		// 模拟注解
		Vector<String> v = new Vector<String>();
//        v.addElement("news");
//        when(servletConfig.getInitParameter("news")).thenReturn("ajaxjs.data.service.News");
//        v.addElement("img");
//        when(servletConfig.getInitParameter("img")).thenReturn("ajaxjs.data.service.subObject.Img");
//        v.addElement("catalog");
//        when(servletConfig.getInitParameter("catalog")).thenReturn("zjtv.SectionService");
//        v.addElement("user");
//        when(servletConfig.getInitParameter("user")).thenReturn("ajaxjs.data.user.UserService");
//        v.addElement("compere");
//        when(servletConfig.getInitParameter("compere")).thenReturn("zjtv.CompereService");
        
		// 通过反射获取注解内容
        Class<?> cls = getBusinessServletClass();
        
        if(cls != null){
    		WebServlet WebServlet_an = cls.getAnnotation(WebServlet.class);
    		
    		for(WebInitParam p : WebServlet_an.initParams()){
    			v.addElement(p.name());
    			when(servletConfig.getInitParameter(p.name())).thenReturn(p.value());
    		}
        }

        Enumeration<String> e = v.elements(); 
		when(servletConfig.getInitParameterNames()).thenReturn(e);
		
		return servletConfig;
	}
	 
    class StubServletOutputStream extends ServletInputStream {  
        public ByteArrayOutputStream baos = new ByteArrayOutputStream();  
        public void write(int i) throws IOException {  
            baos.write(i);  
        }  
        public String getContent() {  
            return baos.toString();  
        }
		@Override
		public int read() throws IOException {
			// TODO Auto-generated method stub
			return 0;
		}  
    } 
    
  
    /**
     * 模拟表单请求
     * @throws IOException 
     */
    public HttpServletRequest initRequest(HttpServletRequest request, Map<String, String> formBody, boolean isByGetParams) throws IOException{
    	if(isByGetParams){
    		for(String key : formBody.keySet()){
    			when(request.getParameter(key)).thenReturn(formBody.get(key));
    		}
    	}else{
    		String form = ajaxjs.Util.HashJoin(formBody);
    		
    		final ByteArrayInputStream is = new ByteArrayInputStream(form.getBytes());
    		when(request.getInputStream()).thenReturn(new ServletInputStream() {
    			@Override
    			public int read() throws IOException {
    				return is.read();
    			}
    		}); 
    	}
    	
    	return request;
    }
    
	/**
	 * 请求对象
	 * @return
	 * @throws IOException 
	 */
	public HttpServletRequest initRequest(String entry){
		HttpServletRequest request = mock(HttpServletRequest.class);
		when(request.getPathInfo()).thenReturn("/zjtv/service/" + entry);
		when(request.getRequestURI()).thenReturn("/zjtv/service/" + entry);
		when(request.getContextPath()).thenReturn("/zjtv");
		
//		when(request.getSession()).thenReturn("/zjtv");
		when(request.getMethod()).thenReturn("GET");
		// 设置参数
		when(request.getParameter("a")).thenReturn("aaa");
		
		final Map<String, Object> hash = new HashMap<String, Object>();
		Answer<String> aswser = new Answer<String>() {  
		    public String answer(InvocationOnMock invocation) {  
		        Object[] args = invocation.getArguments();  
		        Object obj = hash.get(args[0].toString());
		        
		        return obj == null ? null : obj.toString();  
		    }  
		};
		
		when(request.getAttribute("isRawOutput")).thenReturn(true);  
		when(request.getAttribute("errMsg")).thenAnswer(aswser);  
		when(request.getAttribute("msg")).thenAnswer(aswser);  
//		doThrow(new Exception()).when(request).setAttribute(anyString(), anyString());
		
		doAnswer(new Answer<Object>() {
	        public Object answer(InvocationOnMock invocation) {
	            Object[] args = invocation.getArguments();
	            // Object mock = invocation.getMock();  
	            // 测试终端的模拟器接收到数据
	            // System.out.println(args[1]);
	            hash.put(args[0].toString(), args[1]);
	            return "called with arguments: " + args;
	        }
	    }).when(request).setAttribute(anyString(), anyString());
		
		return request;
	}
	
	// 不能返回数组返回一个对象吧
	public class response_writer{
		public HttpServletResponse response;
		public StringWriter writer;
	}
	public response_writer initResponse() throws IOException{
        HttpServletResponse response = mock(HttpServletResponse.class);
        StringWriter writer = new StringWriter();
        
        when(response.getWriter()).thenReturn(new PrintWriter(writer));
        
        response_writer r_w = new response_writer();
        r_w.response = response;
        r_w.writer = writer;
        
        return r_w;
	}
	
	/**
	 * 模拟数据库 链接 的配置
	 * @throws NamingException
	 */
	public static void initDBConnection() throws NamingException{
		 // Create initial context
        System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
        System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming");  
        // 需要加入tomcat-juli.jar这个包，tomcat7此包位于tomcat根目录的bin下。
        InitialContext ic = new InitialContext();
        ic.createSubcontext("java:");
        ic.createSubcontext("java:/comp");
        ic.createSubcontext("java:/comp/env");
        ic.createSubcontext("java:/comp/env/jdbc");
        // Construct DataSource
        try {
			SQLiteJDBCLoader.initialize();
		} catch (Exception e1) {
			e1.printStackTrace();
		}

        SQLiteDataSource dataSource = new SQLiteDataSource();
        dataSource.setUrl("jdbc:sqlite:c:\\project\\zjtv\\WebContent\\META-INF\\zjtv.sqlite");
        
        ic.bind("java:/comp/env/jdbc/sqlite", dataSource);
	}
	
	public static void initDBConnection_Mysql(String MYSQL_DB_URL, String MYSQL_DB_USERNAME, String MYSQL_DB_PASSWORD) throws NamingException{
		// Create initial context
		System.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.apache.naming.java.javaURLContextFactory");
		System.setProperty(Context.URL_PKG_PREFIXES, "org.apache.naming");  
		// 需要加入tomcat-juli.jar这个包，tomcat7此包位于tomcat根目录的bin下。
		InitialContext ic = new InitialContext();
		ic.createSubcontext("java:");
		ic.createSubcontext("java:/comp");
		ic.createSubcontext("java:/comp/env");
		ic.createSubcontext("java:/comp/env/jdbc");
		// Construct DataSource
		MysqlDataSource dataSource = null;
		
		try {
			dataSource = new MysqlDataSource();
			dataSource.setURL(MYSQL_DB_URL);
			dataSource.setUser(MYSQL_DB_USERNAME);
			dataSource.setPassword(MYSQL_DB_PASSWORD);
		} catch (Exception e1) {
			e1.printStackTrace();
		}
		
		
		ic.bind("java:/comp/env/jdbc/mysql_deploy", dataSource);
	}
	
	/**
	 * 进行请求
	 * 在请求之前，你可以设定请求的参数
	 * @throws IOException 
	 * @throws ServletException 
	 */
	public Map<String, Object> doRequest(HttpServletRequest request) throws IOException, ServletException{
		response_writer r_w = initResponse();
        
		BaseServlet bs = new BaseServlet();
		bs.init(initServletConfig());
		bs.doPost(request, r_w.response);
		String output = r_w.writer.toString();
//		System.out.println("ddddddddddddd::::::::::"+output);
		return shouldbe_json_return(output);
	}

	public Map<String, Object> shouldbe_json_return(String js_code){
//		System.out.println("返回 json ：" + js_code);
		return Application.jsRuntime.NativeObject2Hash(js_code);
	}
	
	public boolean shouldbe_hasRecord(Map<String, Object> json){
		boolean hasRecord = false;
		
//		System.out.println(json.get("total"));
		int total = (int)json.get("total");
		System.out.println("获取记录数：" + total);
		hasRecord = total > 0;
		
		return hasRecord;
	}
}
